export = {}
import {Address} from "cluster";

/**Type Inference */
//inference n.推理; 推断;
// 推论;
/*
1. 当赋值时会推断
  - 等号左边根据等号右边来进行推导(赋值能推导)
  - 参数, 如果标识了泛型的位置, 那么会根据使用时的参数进行推导
    class Person{}
    interface IClazzF<T> {
      new(...args: any[]): T;
    }
    function getInstance<T>(Clazz: IClazzF<T>){
      return new Clazz();
    }
    let rr = getInstance<Person>(Person);
    let rr2 = getInstance(Person);
    //↑这里也可以不传<Person>, 可以自动推导

      function getInstance<T>(Clazz: IClazzF<T>) --->
      IClazzF<T> ---> new(...args: any[]): T , 返回T
      也就是说Person == T ---> T 即为 Person
      So 也就可以省略了


2. 函数默认会进行推断
3. 返回值的推断
4. 对象属性或接口属性的推断
5. 类型的反推
*/

//1 初始化变量时,会发生类型推断
//string
let str = ''; //会根据值进行推断
//number
var n = 1;
n.split(''); // TS2339: Property 'split' does not exist on type 'number'.

//2. 函数的推断
//   函数会根据右边的赋值 推导左边的类型
const sum = (a: string, b: string): string/*←这也可以省略*/ => {
  return a + b;
} //↑ 这样sum就不用再 ：type 这样标识类型了

//3. 返回值的推断
function add(n1: string, n2: string)/*会猜测返回为:string,将鼠标移到前面的add ctr+左键点击可知*/ {
  return n1 + n2;
}

const s/*←ts能推断出这个s会是string*/ = add('ahhh', '123');
//故能s.split('') 即调用string的方法
console.log(s.split(''));

//4. 对象属性或接口属性的推断
let person = {
  name: 'ahhh',
  age: 123,
  address: {
    where: {},
    code: {}
  }
}
let {name,address}/*ctrl鼠标左键可见,推导出的类型*/ = person
name = 123 //TS2322: Type '123' is not assignable to type 'string'.
address.where

interface IPerson {
  name: string;
  age: number;
  address:{
    n: string;
  }
}
// type n = IPerson.address //访问接口的某个属性不能使用 . , 必须使用[]
type n = IPerson['address']['n']

